package dlwntk6545;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class J02_Departments {

	public static void main(String[] args) {
		
		
		/*
				1.
				JDBC 드라이버 불러오기
				JDBC 드라이버는 데이터베이스에 연결해야 할 필요가 있는
				자바 클래스와 JDBC 드라이버 사이 계약을 정의하는
				인터페이스들을 구현한 것 드라이버는 jar 파일 형태로 배포
				
				JDBC 드라이버를 불러오는 방법에는
				수동 manual 과 동적 dynamic 이 있음
				Class.forName("oracle.jdbc.driver.OracleDriver");
				Class.forName(DRV);
				
				forName 메서드는 ClassNotFoundException
				예외를 던지기 때문에 try - catch 블럭 안에 둬야 함
				
				2.
				데이터베이스 연결하기
				Connection 인터페이스는 데이터베이스 연결객체를 위한 그릇(템플릿)임
				연결객체를 얻으려면 DriverManager 클래스의
				getConnection 메서드를 이용
				getConnection 메서드는 앞의 과정에서 메모리에 올려둔 드라이버를 찾고
				URL, USR, PWD 를 통해 데이터베이스 서버에 연결을 하고 
				그 결과를 Connection 으로 변환
				
				JDBC 연결시 사용하는 URL 은 다음과 같음
				jdbc:프로토콜:하위이름
				jdbc:oracle:thin:@주소:포트:DB이름?user=아이디&amp;password=비밀번호
				jdbc:mysql://주소/DB이름?user=아이디&password=비밀번호	//&amp; = &이나
																//&amp; 를 쓰는것 추천
				
				3.
				SQL 질의문 생성 및 실행
				Statement, PreparedStatement 객체는 실행할 SQL 질의문을 의미함
				createStatement, preparedStatement 메서드를 이용해서 위 객체를 얻을 수 있음
				단, 메서드를 호출할 때에는 생성할 SQL 질의문을 인자로 전달해야 함
				생성한 객체를 실행하며면 executeQuery나 executeUpdate 메서드를 이용함
				executeQuery : SQL 질의문이 select 인경우
				executeUpdate : insert, update, delete, create, alter, drop 인 경우
				
				executeUpdate 의 실행결과는 질의문에 의해 변경된 레코드 수나 0을 반환
				executeQuery 의 실행결과는 질의문에 의해 생성된 데이터를 담아두는
				ResultSet 객체를 반환 단, 생성된 데이터가 없는 경우 null 은 아님
				
				Statement 에서 파생된 preparedStatement 는 Statement 의 인기있는 대체제임
				SQL 문을 미리 컴파일하고 저장해두기 때문에 
				추후 동일한 SQL 문을 실행할 경우 빠르게 처리된다는 장점이 제공됨
				
				4.
				결과집합은 ResultSet 객체 다루기
				결과집합은 Statement, PreparedStatement 에서 
				반환된 데이터베이스 테이블을 의미함
				결과집합 객체는 현재 데이터 행을 가리키는 커서를 가지고 있음
				커서는 처음에는 테이블을 가리키고 있다가 next 메서드가 호출되면
				다음 레코드로 이동하고 true 또는 false 로 반환함
				true 가 반환되면 현재 레코드가 존재한다는 의미
				false 가 반환되면 더이상 레코드가 없다는 의미
				while 을 이용해서 모든 레코드에 접근할 수 있음
				
				next 메서드로 레코드에 접근한 뒤, 각 필드 값을 가져오려면 getXxx 메서드를 사용해야 함
				일반적으로 필드 값을 문자열로 가져오는 getString 메서드를 많이 사용
				필드값을 int 로 가져오려면 getInt 를 사용하면 됨
				
				getXxx 메서드에 필드이름 또는 필드 위치값을 이용인자로 전달해서 필드값을 가져올 수 있음
				getString(1)
				getString("department_id")
				
				5.
				JDBC 객체 닫기
				모든 JDBC 객체는 사용한 후 그들의 close 메서드를 호출해서 항상 닫아야 함
				try {
						... ...
						... ...
						rs.close();
						pstmt.close();
						conn.close();
				}catch(Exception ex){
					ex.printStackTrace();
				}
				위 코드는 완벽하지 않음
				pstmt.close(); 가 실패하는 경우, 그 아래 코드는 실행되지 않기 때문임
				따라서, close 관련 코드는 finally 절에 작성해야 함
				즉, 예외가 발생하든 하지 않든 간에 무조건 실행되어야 하는 코드는
				finally 절에 작성하면 프로그램이 다소 완벽해 짐 
				
		 */
		
		final String DRV = "oracle.jdbc.driver.OracleDriver";
		final String URL = "jdbc:oracle:thin:@112.216.253.125:1521:xe";
		final String USR = "dlwntk6545";
		final String PWD = "dlwntk6545";
		
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		String SQL = "select * from employees";
		
		try{
			
			Class.forName(DRV);
			conn = DriverManager.getConnection(URL, USR, PWD);
			pstmt = conn.prepareStatement(SQL);
			rs = pstmt.executeQuery();
			if(rs.next()){
			do{
				System.out.println(rs.getString("department_id"));
				System.out.println(rs.getString(2));
				System.out.println(rs.getString("manager_id"));
				System.out.println(rs.getString(4));
				System.out.println();
			}while(rs.next());
			}else{
				System.out.println("데이터가 없쩌영 뿌우~");
			}
		}catch(Exception ex){
			ex.printStackTrace();
		}finally{
			
			if(rs != null)
				try{rs.close(); rs = null;}catch(Exception e){}
			if(rs != null)
				try{pstmt.close(); pstmt = null;}catch(Exception e){}
			if(rs != null)
				try{conn.close(); conn = null;}catch(Exception e){}
			
		}
		
	}
}
